/*
 * <<
 * Davinci
 * ==
 * Copyright (C) 2016 - 2017 EDP
 * ==
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * >>
 */

import { IChartProps } from '../../components/Chart'
import { EChartOption } from 'echarts'
import {
  decodeMetricName,
  getTextWidth,
  getSizeRate
} from '../../components/util'
import {
  getLegendOption,
  getLabelOption,
  getSymbolSize
} from './util'
import {
  safeAddition
} from 'utils/util'

import {
  DEFAULT_ECHARTS_THEME
} from 'app/globalConstants'
import geoData from 'assets/js/geo.js'
import { getFormattedValue } from '../../components/Config/Format'
import { mockDisplayDefaultState } from 'test/app/containers/Display/fixtures'

const provinceSuffix = ['省', '自治区', '市']
const citySuffix = ['自治州', '市', '区', '县', '旗', '盟', '镇']

export default function (chartProps: IChartProps) {
  const {
    chartStyles,
    data,
    cols,
    metrics,
    model
  } = chartProps

  const {
    label,
    spec,
    space,
    map,
    loopTimer
  } = chartStyles

  const {
    labelColor,
    labelFontFamily,
    labelFontSize,
    labelPosition,
    showLabel
  } = label

  const {
    layerType,
    roam,
    linesSpeed,
    symbolType
  } = spec

  const tooltip: EChartOption.Tooltip = {
    trigger: 'item',
    formatter: (params: EChartOption.Tooltip.Format) => {
      const { name, data, color } = params
      const tooltipLabels = []
      if (color) {
        tooltipLabels.push(`<span class="widget-tooltip-circle" style="background: ${color}"></span>`)
      }
      tooltipLabels.push(name)
      if (data) {
        tooltipLabels.push(': ')
        tooltipLabels.push(getFormattedValue(data.value[2], metrics[0].format))
      }
      return tooltipLabels.join('')
    },
    textStyle: {
      color: map.fontColor
    },
    backgroundColor: loopTimer.tooltipColor,
    borderColor: map.tooltipBorder
  }

  const labelOption = {
    label: {
      normal: {
        formatter: '{b}',
        position: labelPosition,
        show: showLabel,
        color: labelColor,
        fontFamily: labelFontFamily,
        fontSize: labelFontSize
      }
    }
  }

  const labelOptionLines = {
    label: getLabelOption('lines', label, metrics, true)
  }

  let metricOptions
  let visualMapOptions

  const dataTree = {}
  let min = 0
  let max = 0

  const agg = metrics[0].agg
  const metricName = decodeMetricName(metrics[0].name)

  data.forEach((record) => {
    let areaVal
    const group = []

    const value = record[`${agg}(${metricName})`]
    min = Math.min(min, value)
    max = Math.max(max, value)
    cols.forEach((col) => {
      const { visualType } = model[col.name]
      if (visualType === 'geoProvince') {
        areaVal = record[col.name]
        const area = getProvinceArea(areaVal)
        const provinceName = getProvinceName(areaVal)
        if (area) {
          if (!dataTree[provinceName]) {
            dataTree[provinceName] = {
              lon: area.lon,
              lat: area.lat,
              value,
              children: {}
            }
          }
        }
      } else if (visualType === 'geoCity') {
        areaVal = record[col.name]
        const area = getCityArea(areaVal)
        if (area) {
          if (layerType === 'map') {
            const provinceParent = getProvinceParent(area)
            const parentName = getProvinceName(provinceParent.name)
            if (!dataTree[parentName]) {
              dataTree[parentName] = {
                lon: area.lon,
                lat: area.lat,
                value: 0,
                children: {}
              }
            }
            dataTree[parentName].value += value
          } else {
            if (!dataTree[areaVal]) {
              dataTree[areaVal] = {
                lon: area.lon,
                lat: area.lat,
                value,
                children: {}
              }
            }
          }
        }
      }

      // todo: 除去显示城市／省的
      // const group = ['name', 'sex']
      // if (group.length) {
      //   group.forEach((g) => {
      //     if (!dataTree[areaVal].children[record[g]]) {
      //       dataTree[areaVal].children[record[g]] = 0
      //     }
      //     dataTree[areaVal].children[record[g]] = safeAddition(dataTree[areaVal].children[record[g]], Number(value))
      //   })
      // }
    })
  })

  // series 数据项
  const metricArr = []

  const sizeRate = getSizeRate(min, max)

  const optionsType = layerType === 'scatter' ? {} : {
    blurSize: 40
  }

  let serieObj
  const myData = [
    { name: '海门', value: [121.15, 31.89, 90] },
    { name: '鄂尔多斯', value: [109.781327, 39.608266, 120] },
    { name: '招远', value: [120.38, 37.35, 142] },
    { name: '舟山', value: [122.207216, 29.985295, 123] }
  ]
  // const mapData = [
  //   { name: '海门', value: 1000 },
  //   { name: '鄂尔多斯', value: 2000 },
  // ]
  switch (layerType) {
    case 'map':
      serieObj = {
        name: '地图',
        type: 'map',
        itemStyle: {
          normal: {
            areaColor: map.bgColor,
            // {
            // color: shadow.startColor,
            //   {
            //     type: shadow.shadowType,
            //     x: 0,
            //     y: 0,
            //     x2: 0,
            //     y2: 1,
            //     colorStops: [{
            //       offset: 0, color: shadow.startColor // 0% 处的颜色
            //     }, {
            //       offset: 1, color: shadow.endColor // 100% 处的颜色
            //     }],
            //     global: false // 缺省为 false
            //   }
            // },
            borderColor: map.borderColor,
            borderWidth: 1
          },
          emphasis: {
            areaColor: map.highlight,
            label: {
              show: map.showLabel,
              color: map.labelColor
            }
          }
        },
        mapType: 'china',
        roam,
        data: Object.keys(dataTree).map((key, index) => {
          const { lon, lat, value } = dataTree[key]
          return {
            name: key,
            value: [lon, lat, value]
          }
        }),
        // coordinateSystem: 'geo',
        // data: mapData,
        ...labelOption
      }
      break
    case 'scatter':
      serieObj = {
        name: '气泡图',
        type: 'scatter',
        itemStyle: {
          normal: {
            areaColor: {
              color: map.bgColor
              //   {
              //     type: shadow.shadowType,
              //     x: 0,
              //     y: 0,
              //     x2: 0,
              //     y2: 1,
              //     colorStops: [{
              //       offset: 0, color: 'red' // 0% 处的颜色
              //     }, {
              //       offset: 1, color: 'red' // 100% 处的颜色
              //     }],
              //     global: false // 缺省为 false
              //   }
            },
            borderColor: map.borderColor,
            borderWidth: 1
          }

          // label: {
          //   emphasis: {
          //     show: map.showLabel,
          //     color: map.labelColor
          //   }
          // },
        },
        emphasis: {
          areaColor: map.highlight,
          // scale: false,
          // itemStyle: {
          //   color: map.highlight
          // },
          label: {
            show: map.showLabel,
            color: map.labelColor
          }
        },
        coordinateSystem: 'geo',
        // data: Object.keys(dataTree).map((key, index) => {
        //   const { lon, lat, value } = dataTree[key]
        //   return {
        //     name: key,
        //     value: [lon, lat, value],
        //     symbolSize: getSymbolSize(sizeRate, value) / 2
        //   }
        // }),
        data: myData,
        ...labelOption,
        ...optionsType
      }
      break
    case 'heatmap':
      serieObj = {
        name: '热力图',
        type: 'heatmap',
        itemStyle: {
          normal: {
            areaColor: {
              color: map.bgColor
              // {
              //   type: shadow.shadowType,
              //   x: 0,
              //   y: 0,
              //   x2: 0,
              //   y2: 1,
              //   colorStops: [{
              //     offset: 0, color: shadow.startColor // 0% 处的颜色
              //   }, {
              //     offset: 1, color: shadow.endColor // 100% 处的颜色
              //   }],
              //   global: false // 缺省为 false
              // }
            },
            borderColor: map.bgColor,
            borderWidth: 1
          },
          emphasis: {
            areaColor: map.highlight
          },
          label: {
            emphasis: {
              show: map.showLabel,
              color: map.labelColor
            }
          }
        },
        coordinateSystem: 'geo',
        data: Object.keys(dataTree).map((key, index) => {
          const { lon, lat, value } = dataTree[key]
          return {
            name: key,
            value: [lon, lat, value],
            symbolSize: getSymbolSize(sizeRate, value) / 2
          }
        }),
        ...labelOption,
        ...optionsType
      }
      break
  }

  metricArr.push(serieObj)
  metricOptions = {
    series: metricArr
  }

  if (chartStyles.visualMap) {
    const {
      showVisualMap,
      visualMapPosition,
      fontFamily,
      fontSize,
      visualMapDirection,
      visualMapWidth,
      visualMapHeight,
      startColor,
      endColor
    } = chartStyles.visualMap

    visualMapOptions = {
      visualMap: {
        show: layerType === 'lines' ? false : showVisualMap,
        min,
        max,
        calculable: true,
        inRange: {
          color: [startColor, endColor]
        },
        ...getPosition(visualMapPosition),
        itemWidth: visualMapWidth,
        itemHeight: visualMapHeight,
        textStyle: {
          fontFamily,
          fontSize
        },
        orient: visualMapDirection
      }
    }
  } else {
    visualMapOptions = {
      visualMap: {
        show: false,
        min,
        max,
        calculable: true,
        inRange: {
          color: DEFAULT_ECHARTS_THEME.visualMapColor
        },
        left: 10,
        bottom: 20,
        itemWidth: 20,
        itemHeight: 50,
        textStyle: {
          fontFamily: 'PingFang SC',
          fontSize: 12
        },
        orient: 'vertical'
      }
    }
  }

  const getGeoCity = cols.filter((c) => model[c.name].visualType === 'geoCity')
  const getGeoProvince = cols.filter((c) => model[c.name].visualType === 'geoProvince')
  const linesSeries = []
  const legendData = []
  let effectScatterType
  let linesType
  data.forEach((d, index) => {
    let linesSeriesData = []
    let scatterData = []
    const value = d[`${agg}(${metricName})`]

    if (getGeoCity.length > 1 && d[getGeoCity[0].name] && d[getGeoCity[1].name]) {
      const fromCityInfo = getCityArea(d[getGeoCity[0].name])
      const toCityInfo = getCityArea(d[getGeoCity[1].name])

      if (fromCityInfo && toCityInfo) {
        legendData.push(d[getGeoCity[0].name])
        linesSeriesData = [{
          fromName: d[getGeoCity[0].name],
          toName: d[getGeoCity[1].name],
          coords: [[fromCityInfo.lon, fromCityInfo.lat], [toCityInfo.lon, toCityInfo.lat]]
        }]
        scatterData = [{
          name: d[getGeoCity[1].name],
          value: [toCityInfo.lon, toCityInfo.lat, value]
        }]
      }
    } else if (getGeoProvince.length > 1 && d[getGeoProvince[0].name] && d[getGeoProvince[1].name]) {
      const fromProvinceInfo = getProvinceArea(d[getGeoProvince[0].name])
      const toProvinceInfo = getProvinceArea(d[getGeoProvince[1].name])

      if (fromProvinceInfo && toProvinceInfo) {
        legendData.push(d[getGeoProvince[0].name])
        linesSeriesData = [{
          fromName: d[getGeoProvince[0].name],
          toName: d[getGeoProvince[1].name],
          coords: [[fromProvinceInfo.lon, fromProvinceInfo.lat], [toProvinceInfo.lon, toProvinceInfo.lat]]
        }]
        scatterData = [{
          name: d[getGeoProvince[1].name],
          value: [toProvinceInfo.lon, toProvinceInfo.lat, value]
        }]
      }
    } else {
      return
    }

    effectScatterType = {
      name: '',
      type: 'effectScatter',
      coordinateSystem: 'geo',
      zlevel: index,
      rippleEffect: {
        brushType: 'stroke'
      },
      ...labelOptionLines,
      symbolSize: (val) => {
        return 12
      },
      data: scatterData
    }

    linesType = {
      name: '',
      type: 'lines',
      zlevel: index,
      symbol: ['none', 'arrow'],
      symbolSize: 10,
      effect: {
        show: true,
        // period: 600,
        trailLength: 0,
        symbol: symbolType,
        symbolSize: 15,
        constantSpeed: linesSpeed
      },
      lineStyle: {
        normal: {
          width: 2,
          opacity: 0.6,
          curveness: 0.2
        }
      },
      data: linesSeriesData
    }
    linesSeries.push(linesType, effectScatterType)
  })

  let legendOption
  if (chartStyles.legend) {
    const {
      color,
      fontFamily,
      fontSize,
      legendPosition,
      selectAll,
      showLegend
    } = chartStyles.legend
    legendOption = {
      legend: getLegendOption(chartStyles.legend, legendData, 'plain')
    }
  } else {
    legendOption = null
  }

  let mapOptions
  switch (layerType) {
    case 'map':
      mapOptions = {
        geo: {
          map: 'china'
          // center: [115.83531246, 34.0267395887]
        },
        ...metricOptions,
        ...visualMapOptions,
        tooltip
      }
      break
    case 'lines':
      // 飞行图
      mapOptions = {
        ...legendOption,
        geo: {
          map: 'china',
          itemStyle: {
            normal: {
              areaColor: map.bgColor,
              // {
              // color: {
              //   type: shadow.shadowType,
              //   x: 0,
              //   y: 0,
              //   x2: 0,
              //   y2: 1,
              //   colorStops: [{
              //     offset: 0, color: shadow.startColor // 0% 处的颜色
              //   }, {
              //     offset: 1, color: shadow.endColor // 100% 处的颜色
              //   }],
              //   global: false // 缺省为 false
              // }
              // },
              borderColor: map.borderColor,
              borderWidth: 1
            },
            emphasis: {
              areaColor: map.highlight,
              label: {
                show: map.showLabel,
                color: map.labelColor
              }
            },
            label: {
              formatter: '{b}',
              position: 'right'
              // emphasis: {
              //   show: map.showLabel,
              //   color: map.labelColor
              // }
            }
          },
          roam
        },
        series: linesSeries,
        ...visualMapOptions
      }
      break
    case 'scatter':
      mapOptions = {
        geo: {
          map: 'china',
          itemStyle: {
            normal: {
              areaColor: map.bgColor,
              // {
              //   color: {
              //     type: shadow.shadowType,
              //     x: 0,
              //     y: 0,
              //     x2: 0,
              //     y2: 1,
              //     colorStops: [{
              //       offset: 0, color: shadow.startColor // 0% 处的颜色
              //     }, {
              //       offset: 1, color: shadow.endColor // 100% 处的颜色
              //     }],
              //     global: false // 缺省为 false
              //   }
              // },
              borderColor: map.borderColor,
              borderWidth: 1
            },
            emphasis: {
              areaColor: map.highlight,
              // scale: false,
              // itemStyle: {
              //   color: map.highlight
              // },
              label: {
                show: map.showLabel,
                color: map.labelColor
              }
            },
            label: {
              formatter: '{b}',
              position: 'right'
              // emphasis: {
              //   show: map.showLabel,
              //   color: map.labelColor
              // }
            }
          },
          roam
        },
        ...metricOptions,
        ...visualMapOptions,
        tooltip
      }
      break
    case 'heatmap':
      // 热力图
      mapOptions = {
        geo: {
          map: 'china',
          itemStyle: {
            normal: {
              areaColor: map.bgColor,
              // {
              //   color: {
              //     type: shadow.shadowType,
              //     x: 0,
              //     y: 0,
              //     x2: 0,
              //     y2: 1,
              //     colorStops: [{
              //       offset: 0, color: shadow.startColor // 0% 处的颜色
              //     }, {
              //       offset: 1, color: shadow.endColor // 100% 处的颜色
              //     }],
              //     global: false // 缺省为 false
              //   }
              // },
              borderColor: map.borderColor,
              borderWidth: 1
            },
            emphasis: {
              areaColor: map.highlight
            }
            // {
            //   areaColor: {
            //     color: {
            //       type: shadow.shadowType,
            //       x: 0,
            //       y: 0,
            //       x2: 0,
            //       y2: 1,
            //       colorStops: [{
            //         offset: 0, color: shadow.startColor // 0% 处的颜色
            //       }, {
            //         offset: 1, color: shadow.endColor // 100% 处的颜色
            //       }],
            //       global: false // 缺省为 false
            //     }
            //   }
            // }
          },
          label: {
            emphasis: {
              show: map.showLabel,
              color: map.labelColor
            }
          },
          roam
        },
        ...metricOptions,
        ...visualMapOptions
        // ...tooltipOptions
      }
      break
  }

  return mapOptions
}

function getProvinceParent(area) {
  if (!area.parent) {
    return area
  }
  const parent = geoData.find((g) => g.id === area.parent)
  return !parent.parent ? parent : getProvinceParent(parent)
}

function getProvinceName(name) {
  provinceSuffix.forEach((ps) => {
    if (name.includes(ps)) {
      name = name.replace(ps, '')
    }
  })
  return name
}

function getCityArea(name) {
  const hasSuffix = citySuffix.some((p) => name.includes(p))
  const area = hasSuffix
    ? geoData.find((d) => d.name === name)
    : geoData.find((d) => d.name.includes(name))
  return area
}

function getProvinceArea(name) {
  const hasSuffix = provinceSuffix.some((p) => name.includes(p))
  const area = hasSuffix
    ? geoData.find((d) => d.name === name && !d.parent)
    : geoData.find((d) => d.name.includes(name) && !d.parent)
  return area
}

function getPosition(position) {
  let positionValue
  switch (position) {
    case 'leftBottom':
      positionValue = {
        left: 'left',
        top: 'bottom'
      }
      break
    case 'leftTop':
      positionValue = {
        left: 'left',
        top: 'top'
      }
      break
    case 'rightTop':
      positionValue = {
        left: 'right',
        top: 'top'
      }
      break
    case 'rightBottom':
      positionValue = {
        left: 'right',
        top: 'bottom'
      }
      break
  }
  return positionValue
}
